using System;
using System.Xml;
using System.IO;
using System.Text;
using System.Collections;

using Icodeon.Util;

namespace Icodeon.Xhtml
{
    /// <summary>
    /// Utility class to act as a wrapper around a strict XHTML document instance. The class provides some
    /// accessor methods to some key elements and attributes in the XHTML document instance
    /// </summary>
    public sealed class XhtmlDocumentStrict
    {
        private IHtml html;
        private XmlDocument document;

        public XhtmlDocumentStrict()
        {
        }

        /// <summary>
        /// Reads the strict XHTML file to memory from disk
        /// </summary>
        /// <param name="xhtmlFile">The strict XHTML file</param>
        public void Load(FileInfo xhtmlFile)
        {
            this.document = new XmlDocument();
            this.document.Load(xhtmlFile.FullName);
            if (this.document.NamespaceURI.Equals("http://www.w3.org/1999/xhtml"))
            {
                throw new ArgumentException("Namespace is not http://www.w3.org/1999/xhtml : " + this.document.NamespaceURI);
            }
            this.html = new Html(this.document.DocumentElement);
        }

        /// <summary>
        /// Writes the strict XHTML file to disk from memory
        /// </summary>
        /// <param name="xhtmlFile"></param>
        public void Serialize(FileInfo xhtmlFile)
        {
            Icodeon.Xml.Serializer serializer = new Icodeon.Xml.Serializer();
            serializer.SerializeToFile(this.document, xhtmlFile, "http://www.w3.org/1999/xhtml");
        }

        /// <summary>
        /// Returns the root <html/> element
        /// </summary>
        public IHtml RootElement
        {
            get
            {
                return this.html;
            }
        }
    }

    public interface IHtml
    {
        IFrameset GetTopLevelFrameset();
    }

    public interface IFrameset
    {
        IFrame[] GetFrames();
    }

    public interface IFrame
    {
        string GetSrc();
        void SetSrc(string src);
    }

    public sealed class Html : IHtml
    {
        private IFrameset topLevelFrameSet;
        private XmlUtils xmlUtils;

        public Html(XmlElement element)
        {
            if (!element.LocalName.ToLower().Equals("html"))
            {
                throw new ArgumentException("Element is not <html> : " + element.LocalName);
            }
            this.xmlUtils = new XmlUtils();
            this.topLevelFrameSet =
                new Frameset(this.xmlUtils.GetNamedChildElement(element, "frameset"));
        }

        public IFrameset GetTopLevelFrameset()
        {

            return this.topLevelFrameSet;
        }
    }

    public sealed class Frameset : IFrameset
    {
        private IFrame[] frames;
        private XmlUtils xmlUtils;

        public Frameset(XmlElement element)
        {
            if (!element.LocalName.ToLower().Equals("frameset"))
            {
                throw new ArgumentException("Element is not <frameset> : " + element.LocalName);
            }
            this.xmlUtils = new XmlUtils();
            XmlElement[] elements = this.xmlUtils.GetNamedChildElements(element, "frame");
            ArrayList arrayList = new ArrayList();
            for (int i = 0; i < elements.Length; i++)
            {
                arrayList.Add(new Frame(elements[i]));
            }
            this.frames = (IFrame[])arrayList.ToArray(typeof(IFrame));
        }


        public IFrame[] GetFrames()
        {
            return this.frames;
        }
    }

    public sealed class Frame : IFrame
    {
        private XmlUtils xmlUtils;
        private XmlElement element;
        public Frame(XmlElement element)
        {
            if (!element.LocalName.ToLower().Equals("frame"))
            {
                throw new ArgumentException("Element is not <frame> : " + element.LocalName);
            }
            this.element = element;
            this.xmlUtils = new XmlUtils();
        }

        public string GetSrc()
        {
            return this.xmlUtils.GetAttributeValue(this.element, "src");
        }

        public void SetSrc(string src)
        {
            this.xmlUtils.SetAttributeValue(this.element, "src", src);
        }

    }
}
